#include "bootpack.h"
#include <stdio.h>
#define PORT_KEYDAT 0x0060 /* 键盘端口 */

/* PIC的初始化 */
void init_pic(void)
{
    io_out8(PIC0_IMR, 0xff); /* 禁止所有中断，防止冲突 */
    io_out8(PIC1_IMR, 0xff); /* 禁止所有中断 */

    io_out8(PIC0_ICW1, 0x11);   /* 边沿触发模式（edge trigger mode） */
    io_out8(PIC0_ICW2, 0x20);   /* IRQ0-7由INT20-27接收 */
    io_out8(PIC0_ICW3, 1 << 2); /* PIC1由IRQ2连接 00000100 */
    io_out8(PIC0_ICW4, 0x01);   /* 无缓冲区模式 */

    io_out8(PIC1_ICW1, 0x11); /* 边沿触发模式（edge trigger mode） */
    io_out8(PIC1_ICW2, 0x28); /* IRQ0-7由INT20-27接收 */
    io_out8(PIC1_ICW3, 2);    /* PIC1由IRQ2连接 不懂= = */
    io_out8(PIC1_ICW4, 0x01); /* 无缓冲区模式 */

    io_out8(PIC0_IMR, 0xfb); /* 11111011 PIC1以外全部禁止 */
    io_out8(PIC1_IMR, 0xff); /* 11111111 禁止所有中断 */

    return;
}

/**
 * 来自PS/2键盘的中断
 * 鼠标是IRQ12
 * 键盘是IRQ1
 */
void inthandler21(int *esp)
{
    struct BOOTINFO *binfo = (struct BOOTINFO *)ADR_BOOTINFO;
    unsigned char data, s[4];
    io_out8(PIC0_OCW2, 0x61); /* 通知PIC “IRQ-01已经受理完毕”，将 “0x60+IRQ号码” 输出给OCW2就可以 */
    data = io_in8(PORT_KEYDAT);

    sprintf(s, "%02X", data); /* %02X 2位十六进制数 */
    boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
    putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
    return;
}

/* 从PS/2鼠标中断 */
void inthandler2c(int *esp)
{
    struct BOOTINFO *binfo = (struct BOOTINFO *)ADR_BOOTINFO;
    boxfill8(binfo->vram, binfo->scrnx, COL8_000000, 0, 0, 32 * 8 - 1, 15);
    putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, "INT 2C (IRQ-12) : PS/2 mouse");
    for (;;)
    {
        io_hlt();
    }
}

/* 防止来自PIC0的不完整中断的措施 */
/* 在Athlon64X2机器等中，由于芯片组情况，此中断在PIC初始化时仅发生一次。 */
/* 该中断处理功能对该中断不起作用 */
/* 为什么你不必做任何事情
	→  由于此中断是由PIC初始化时的电气噪声产生的，
		您不必认真做任何事情。	                */
void inthandler27(int *esp)
{
    io_out8(PIC0_OCW2, 0x67); /* 通知PIC IRQ-07接受（请参阅7-1）*/
    return;
}
